package com.lry.basic.jvm.asm.transform_class.demo20;
import aj.org.objectweb.asm.ClassWriter;
import aj.org.objectweb.asm.MethodVisitor;

import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;

import static aj.org.objectweb.asm.Opcodes.*;

public class MyClassLoader extends ClassLoader{

    public static void main(String[] args) throws Exception {

        MyClassLoader mcl = new MyClassLoader();

        Class clazz = mcl.findClass("CalPointsImpl");

        Object obj = clazz.newInstance();

        Method method = clazz.getDeclaredMethod("calPoints",long.class);

        System.out.println(method.invoke(obj, 1));
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        if(name.equals("CalPointsImpl")){


            byte[] b = dump(name);

            return defineClass(name,b,0,b.length);
        }
        return super.findClass(name);
    }

    private byte[] dump2(String name){
        String code = "package com.lry.basic.jvm.asm.transform_class.demo20;\n" +
                "\n" +
                "public class CalPointsImpl implements CalPoints{\n" +
                "    @Override\n" +
                "    public long calPoints(long points) {\n" +
                "        points = points*2;\n" +
                "        return points;\n" +
                "    }\n" +
                "}\n";

        return code.getBytes(StandardCharsets.UTF_8);
    }

    private byte[] dump(String name){
        // (1) 创建ClassWriter对象
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);

        // (2) 调用visitXxx()方法
        cw.visit(V1_8,ACC_PUBLIC,
                name,
                null,"java/lang/Object",
                new String[]{"com/lry/basic/jvm/asm/transform_class/demo20/CalPoints"});

        {
            MethodVisitor mv1 = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
            mv1.visitCode();
            mv1.visitVarInsn(ALOAD, 0);
            mv1.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
            mv1.visitInsn(RETURN);
            mv1.visitMaxs(0, 0);
            mv1.visitEnd();
        }

        {
            //points=points*2;

            MethodVisitor mv2 = cw.visitMethod(ACC_PUBLIC, "calPoints", "(J)J", null, null);
            mv2.visitCode();

            mv2.visitVarInsn(LLOAD,1);

            mv2.visitLdcInsn(2L);
            mv2.visitInsn(LMUL);

            mv2.visitVarInsn(LSTORE,1);
            mv2.visitVarInsn(LLOAD,1);
            mv2.visitInsn(LRETURN);
            mv2.visitMaxs(0, 0);
            mv2.visitEnd();
        }

        cw.visitEnd();

        // (3) 调用toByteArray()方法
       return cw.toByteArray();
    }

}